﻿using CSRedis;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Sprout.Cache.Redis
{
    public static partial class RedisService
    {
        #region
        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="redisClient">redis客户端</param>
        /// <param name="key">key</param>
        /// <returns></returns>
        public static async Task<bool> ExpireAsync(CSRedisClient redisClient, string key)
        {
            TimeSpan? expire = GetExpire(key);

            if (expire.HasValue)
            {
                return await redisClient.ExpireAsync(key, expire.Value);
            }
            else
            {
                return await redisClient.PersistAsync(key);
            }
        }

        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="redisClient">redis客户端</param>
        /// <param name="key">key</param>
        /// <param name="expire">过期时间</param>
        /// <returns></returns>
        public static async Task<bool> ExpireAsync(CSRedisClient redisClient, string key, TimeSpan expire)
        {
            return await redisClient.ExpireAsync(key, expire);
        }

        #endregion

        #region key
        /// <summary>
        /// 删除缓存
        /// 如果多个key必须在同一个db中
        /// </summary>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns>是否成功</returns>
        public static async Task<long> DelAsync(params string[] keys)
        {
            if (keys == null || keys.Length == 0)
            {
                return 0;
            }
            var redisClient = GetRedisClient(keys);
            var count = await redisClient.DelAsync(keys);
            return count;
        }

        /// <summary>
        /// 检查给定 key 是否存在
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> ExistsAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ExistsAsync(key);
        }
        /// <summary>
        /// 为给定 key 设置过期时间
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="seconds">过期秒数</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> ExpireAsync(string key, int seconds)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ExpireAsync(key, seconds);
        }
        /// <summary>
        /// 为给定 key 设置过期时间
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="expire">过期时间</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> ExpireAsync(string key, TimeSpan expire)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ExpireAsync(key, expire);
        }

        /// <summary>
        /// 为给定 key 设置过期时间
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> ExpireAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            TimeSpan? expire = GetExpire(key);
            if (expire.HasValue)
            {
                return await redisClient.ExpireAsync(key, expire.Value);
            }
            else
            {
                return await redisClient.PersistAsync(key);
            }
        }
        /// <summary>
        /// 为给定 key 设置过期时间，指定时间过期
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="expire">指定时间</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> ExpireAtAsync(string key, DateTime expire)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ExpireAtAsync(key, expire);
        }
        /// <summary>
        /// 该返回给定 key 锁储存的值所使用的内部表示(representation)
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string> ObjectEncodingAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ObjectEncodingAsync(key);
        }

        /// <summary>
        /// 该返回给定 key 引用所储存的值的次数。此命令主要用于除错
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long?> ObjectRefCountAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ObjectRefCountAsync(key);
        }

        /// <summary>
        /// 返回给定 key 自储存以来的空转时间(idle， 没有被读取也没有被写入)，以秒为单位
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long?> ObjectIdleTimeAsync(string key)
        {
            var redisClient = GetRedisClient(key);

            return await redisClient.ObjectIdleTimeAsync(key);
        }

        /// <summary>
        /// 移除 key 的过期时间，key 将持久保持
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<bool> PersistAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.PersistAsync(key);
        }

        /// <summary>
        /// 以秒为单位，返回给定 key 的剩余生存时间
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long> TtlAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.TtlAsync(key);
        }

        /// <summary>
        /// 以毫秒为单位返回 key 的剩余的过期时间
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long> PTtlAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.PTtlAsync(key);
        }

        /// <summary>
        /// 修改 key 的名称,newKey存在时覆盖
        /// </summary>
        /// <param name="key">旧名称</param>
        /// <param name="newKey">新名称</param>
        /// <returns></returns>
        public static async Task<bool> RenameAsync(string key, string newKey)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.RenameAsync(key, newKey);
        }

        /// <summary>
        /// 修改 key 的名称，newKey存在时，返回失败
        /// </summary>
        /// <param name="key">旧名称，不含prefix前辍</param>
        /// <param name="newKey">新名称，不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<bool> RenameNxAsync(string key, string newKey)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.RenameNxAsync(key, newKey);
        }

        /// <summary>
        /// 查询keys，会加上前缀
        /// </summary>
        /// <param name="pattern">匹配</param>
        /// <returns>key数组</returns>
        public static async Task<string[]> KeysAsync(string pattern)
        {
            var redisClient = GetRedisClient(pattern);
            string prefix = GetPrefix(redisClient);
            pattern = string.Concat(prefix, pattern);
            var keys = await redisClient.KeysAsync(pattern);
            return RemovePrefix(prefix, keys);
        }

        #endregion

        #region String

        /// <summary>
        /// 如果 key 已经存在并且是一个字符串， APPEND 命令将指定的 value 追加到该 key 原来值（value）的末尾
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">字符串</param>
        /// <returns>追加指定值之后， key 中字符串的长度</returns>
        public static async Task<long> AppendAsync(string key, string value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.AppendAsync(key, value);
        }

        /// <summary>
        /// 获取指定 key 的值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GetAsync(key);
        }

        /// <summary>
        /// 获取指定 key 的值
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GetAsync<T>(key);
        }

        /// <summary>
        /// 返回 key 中字符串值的子字符
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="end">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<string> GetRangeAsync(string key, long start, long end)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GetRangeAsync(key, start, end);
        }

        /// <summary>
        /// 将给定 key 的值设为 value ，并返回 key 的旧值(old value)
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public static async Task<string> GetSetAsync(string key, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GetSetAsync(key, value);
        }

        /// <summary>
        /// 将给定 key 的值设为 value ，并返回 key 的旧值(old value)
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public static async Task<T> GetSetAsync<T>(string key, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GetSetAsync<T>(key, value);
        }

        /// <summary>
        /// 获取多个指定 key 的值(数组)，必须在同一个db中
        /// </summary>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string[]> MGetAsync(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.MGetAsync(keys);
        }

        /// <summary>
        /// 获取多个指定 key 的值(数组)，必须在同一个db中
        /// </summary>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T[]> MGetAsync<T>(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.MGetAsync<T>(keys);
        }
        /// <summary>
        /// 设置指定 key 的值，所有写入参数object都支持string | byte[] | 数值 | 对象
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">值</param>
        /// <param name="expireSeconds">过期(秒单位)</param>
        /// <param name="exists">Nx, Xx</param>
        /// <returns></returns>
        public static async Task<bool> SetAsync(string key, object value, int expireSeconds = -1, RedisExistence? exists = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SetAsync(key, value, expireSeconds, exists);
        }
        /// <summary>
        /// 设置指定 key 的值，所有写入参数object都支持string | byte[] | 数值 | 对象
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">值</param>
        /// <param name="expire">过期时间</param>
        /// <param name="exists">Nx, Xx</param>
        /// <returns></returns>
        public static async Task<bool> SetAsync(string key, object value, TimeSpan expire, RedisExistence? exists = null)
        {
            var redisClient = GetRedisClient(key);
            int expireSeconds = (int)expire.TotalSeconds;
            return await redisClient.SetAsync(key, value, expireSeconds, exists);
        }

        /// <summary>
        /// 返回 key 所储存的字符串值的长度
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long> StrLenAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.StrLenAsync(key);
        }

        /// <summary>
        /// 只有在 key 不存在时设置 key 的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<bool> SetNxAsync(string key, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SetNxAsync(key, value);
        }

        #endregion

        #region Hash

        /// <summary>
        /// 删除一个或多个哈希表字段
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="fields">字段</param>
        /// <returns></returns>
        public static async Task<long> HDelAsync(string key, params string[] fields)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HDelAsync(key, fields);
        }

        /// <summary>
        /// 查看哈希表 key 中，指定的字段是否存在
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="field">字段</param>
        /// <returns></returns>
        public static async Task<bool> HExistsAsync(string key, string field)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HExistsAsync(key, field);
        }

        /// <summary>
        /// 获取存储在哈希表中指定字段的值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="field">字段</param>
        /// <returns></returns>
        public static async Task<string> HGetAsync(string key, string field)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HGetAsync(key, field);
        }
        /// <summary>
        /// 获取存储在哈希表中指定字段的值
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="field">字段</param>
        /// <returns></returns>
        public static async Task<T> HGetAsync<T>(string key, string field)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HGetAsync<T>(key, field);
        }

        /// <summary>
        /// 获取在哈希表中指定 key 的所有字段和值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<Dictionary<string, string>> HGetAllAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HGetAllAsync(key);
        }

        /// <summary>
        /// 获取在哈希表中指定 key 的所有字段和值
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<Dictionary<string, T>> HGetAllAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HGetAllAsync<T>(key);
        }

        /// <summary>
        /// 获取所有哈希表中的字段
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string[]> HKeysAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HKeysAsync(key);
        }
        /// <summary>
		/// 获取哈希表中字段的数量
		/// </summary>
		/// <param name="key">不含prefix前辍</param>
		/// <returns></returns>
		public static async Task<long> HLenAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HLenAsync(key);
        }

        /// <summary>
        /// 获取存储在哈希表中多个字段的值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="fields">字段</param>
        /// <returns></returns>
        public static async Task<string[]> HMGetAsync(string key, params string[] fields)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HMGetAsync(key);
        }

        /// <summary>
        /// 获取存储在哈希表中多个字段的值
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="fields">一个或多个字段</param>
        /// <returns></returns>
        public static async Task<T[]> HMGetAsync<T>(string key, params string[] fields)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HMGetAsync<T>(key);
        }
        /// <summary>
        /// 同时将多个 field-value (域-值)对设置到哈希表 key 中
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="keyValues">key1 value1 [key2 value2]</param>
        /// <returns></returns>
        public static async Task<bool> HMSetAsync(string key, params object[] keyValues)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HMSetAsync(key, keyValues);
        }

        /// <summary>
        /// 同时将多个 field-value (域-值)对设置到哈希表 key 中
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="fieldValues">一个或多个 field value 值</param>
        /// <returns></returns>
        public static async Task<bool> HMSetAsync(string key, params HashAddDto[] fieldValues)
        {
            List<object> list = new List<object>();
            foreach (var item in fieldValues)
            {
                list.Add(item.Field);
                list.Add(item.Value);
            }
            var redisClient = GetRedisClient(key);
            return await redisClient.HMSetAsync(key, list.ToArray());
        }

        /// <summary>
        /// 将哈希表 key 中的字段 field 的值设为 value
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns>如果字段是哈希表中的一个新建字段，并且值设置成功，返回true。如果哈希表中域字段已经存在且旧值已被新值覆盖，返回false。</returns>
        public static async Task<bool> HSetAsync(string key, string field, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HSetAsync(key, field, value);
        }
        /// <summary>
        /// 迭代哈希表中的键值对
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="cursor">位置</param>
        /// <param name="pattern">模式</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static async Task<RedisScan<(string field, string value)>> HScanAsync(string key, int cursor, string pattern = null, int? count = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HScanAsync(key, cursor, pattern, count);
        }

        /// <summary>
        /// 迭代哈希表中的键值对
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="cursor">位置</param>
        /// <param name="pattern">模式</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static async Task<RedisScan<(string field, T value)>> HScanAsync<T>(string key, int cursor, string pattern = null, int? count = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.HScanAsync<T>(key, cursor, pattern, count);
        }

        #endregion

        #region List

        /// <summary>
        /// 获取列表指定范围内的元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<string[]> LRangeAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LRangeAsync(key, start, stop);
        }

        /// <summary>
        /// 获取列表指定范围内的元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<T[]> LRangeAsync<T>(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LRangeAsync<T>(key, start, stop);
        }

        /// <summary>
        /// 获取列表长度
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long> LLenAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LLenAsync(key);
        }

        /// <summary>
        /// 通过索引获取列表中的元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public static async Task<string> LIndexAsync(string key, long index)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LIndexAsync(key, index);
        }

        /// <summary>
        /// 通过索引获取列表中的元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public static async Task<T> LIndexAsync<T>(string key, long index)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LIndexAsync<T>(key, index);
        }
        /// <summary>
        /// 根据参数 count 的值，移除列表中与参数 value 相等的元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="count">移除的数量，大于0时从表头删除数量count，小于0时从表尾删除数量-count，等于0移除所有</param>
        /// <param name="value">元素</param>
        /// <returns></returns>
        public static async Task<long> LRemAsync(string key, long count, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LRemAsync(key, count, value);
        }
        /// <summary>
        /// 通过索引设置列表元素的值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="index">索引</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public static async Task<bool> LSetAsync(string key, long index, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LSetAsync(key, index, value);
        }

        /// <summary>
        /// 对一个列表进行修剪，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<bool> LTrimAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LTrimAsync(key, start, stop);
        }

        /// <summary>
        /// 移出并获取列表的第一个元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string> LPopAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LPopAsync(key);
        }
        /// <summary>
        /// 移出并获取列表的第一个元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T> LPopAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LPopAsync<T>(key);
        }
        /// <summary>
        /// 移除并获取列表最后一个元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string> RPopAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.RPopAsync(key);
        }

        /// <summary>
        /// 移除并获取列表最后一个元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T> RPopAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.RPopAsync<T>(key);
        }

        /// <summary>
        /// 在列表中添加一个或多个值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">一个或多个值</param>
        /// <returns>执行 RPUSH 命令后，列表的长度</returns>
        public static async Task<long> RPushAsync<T>(string key, params T[] value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.RPushAsync(key, value);
        }
        /// <summary>
        /// 为已存在的列表添加值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">一个或多个值</param>
        /// <returns>执行 RPUSHX 命令后，列表的长度</returns>
        public static async Task<long> RPushXAsync(string key, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.RPushXAsync(key, value);
        }
        /// <summary>
        /// 将一个或多个值插入到列表头部
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">一个或多个值</param>
        /// <returns>执行 LPUSH 命令后，列表的长度</returns>
        public static async Task<long> LPushAsync<T>(string key, params T[] value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LPushAsync(key, value);
        }
        /// <summary>
        /// 将一个值插入到已存在的列表头部
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="value">值</param>
        /// <returns>执行 LPUSHX 命令后，列表的长度。</returns>
        public static async Task<long> LPushXAsync(string key, object value)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.LPushXAsync(key, value);
        }
        #endregion

        #region Set

        /// <summary>
        /// 向集合添加一个或多个成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="members">一个或多个成员</param>
        /// <returns></returns>
        public static async Task<long> SAddAsync<T>(string key, params T[] members)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SAddAsync(key, members);
        }

        /// <summary>
        /// 获取集合的成员数
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long> SCardAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SCardAsync(key);
        }

        /// <summary>
        /// 返回给定所有集合的差集
        /// </summary>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string[]> SDiffAsync(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.SDiffAsync(keys);
        }

        /// <summary>
        /// 返回给定所有集合的差集
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T[]> SDiffAsync<T>(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.SDiffAsync<T>(keys);
        }
        /// <summary>
        /// 返回给定所有集合的交集
        /// </summary>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string[]> SInterAsync(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.SInterAsync(keys);
        }
        /// <summary>
        /// 返回给定所有集合的交集
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T[]> SInterAsync<T>(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.SInterAsync<T>(keys);
        }

        /// <summary>
        /// 判断 member 元素是否是集合 key 的成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <returns></returns>
        public static async Task<bool> SIsMemberAsync(string key, object member)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SIsMemberAsync(key, member);
        }

        /// <summary>
        /// 返回集合中的所有成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string[]> SMembersAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SMembersAsync(key);
        }

        /// <summary>
        /// 返回集合中的所有成员
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T[]> SMembersAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);

            return await redisClient.SMembersAsync<T>(key);
        }

        /// <summary>
        /// 移除并返回集合中的一个随机元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string> SPopAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SPopAsync(key);
        }

        /// <summary>
        /// 移除并返回集合中的一个随机元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T> SPopAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SPopAsync<T>(key);
        }

        /// <summary>
        /// 返回集合中的一个随机元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string> SRandMemberAsync(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SRandMemberAsync(key);
        }

        /// <summary>
        /// 返回集合中的一个随机元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T> SRandMemberAsync<T>(string key)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SRandMemberAsync<T>(key);
        }

        /// <summary>
        /// 返回集合中一个或多个随机数的元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="count">返回个数</param>
        /// <returns></returns>
        public static async Task<string[]> SRandMembersAsync(string key, int count = 1)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SRandMembersAsync(key);
        }

        /// <summary>
        /// 返回集合中一个或多个随机数的元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="count">返回个数</param>
        /// <returns></returns>
        public static async Task<T[]> SRandMembersAsync<T>(string key, int count = 1)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SRandMembersAsync<T>(key);
        }

        /// <summary>
        /// 移除集合中一个或多个成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="members">一个或多个成员</param>
        /// <returns></returns>
        public static async Task<long> SRemAsync<T>(string key, params T[] members)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SRemAsync(key, members);
        }

        /// <summary>
        /// 返回所有给定集合的并集
        /// </summary>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<string[]> SUnionAsync(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.SUnionAsync(keys);
        }

        /// <summary>
        /// 返回所有给定集合的并集
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="keys">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<T[]> SUnionAsync<T>(params string[] keys)
        {
            var redisClient = GetRedisClient(keys);
            return await redisClient.SUnionAsync<T>(keys);
        }

        /// <summary>
        /// 迭代集合中的元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="cursor">位置</param>
        /// <param name="pattern">模式</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static async Task<RedisScan<string>> SScanAsync(string key, int cursor, string pattern = null, int? count = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SScanAsync(key, cursor, pattern, count);
        }

        /// <summary>
        /// 迭代集合中的元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="cursor">位置</param>
        /// <param name="pattern">模式</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static async Task<RedisScan<T>> SScanAsync<T>(string key, int cursor, string pattern = null, int? count = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.SScanAsync<T>(key, cursor, pattern, count);
        }

        #endregion

        #region Sorted Set

        /// <summary>
        /// 向有序集合添加一个或多个成员，或者更新已存在成员的分数
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="scoreMembers">一个或多个成员分数</param>
        /// <returns></returns>
        public static async Task<long> ZAddAsync(string key, params (decimal score, object member)[] scoreMembers)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZAddAsync(key, scoreMembers);
        }

        /// <summary>
        /// 向有序集合添加一个或多个成员，或者更新已存在成员的分数
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="scoreMembers">一个或多个成员分数</param>
        /// <returns></returns>
        public static async Task<long> ZAddAsync(string key, params SortedSetAddDto[] scoreMembers)
        {
            List<(decimal, object)> list = new List<(decimal, object)>();
            foreach (var item in scoreMembers)
            {
                list.Add((item.Score, item.Member));
            }
            var redisClient = GetRedisClient(key);
            return await redisClient.ZAddAsync(key, list.ToArray());
        }

        /// <summary>
        /// 获取有序集合的成员数量
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <returns></returns>
        public static async Task<long> ZCardAsync(string key)
        {
            var redisClient = GetRedisClient(key);

            return await redisClient.ZCardAsync(key);
        }

        /// <summary>
        /// 计算在有序集合中指定区间分数的成员数量
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <returns></returns>
        public static async Task<long> ZCountAsync(string key, decimal min, decimal max)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZCountAsync(key, min, max);
        }

        /// <summary>
        /// 计算在有序集合中指定区间分数的成员数量
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <returns></returns>
        public static async Task<long> ZCountAsync(string key, string min, string max)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZCountAsync(key, min, max);
        }

        /// <summary>
        /// 有序集合中对指定成员的分数加上增量 increment
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="increment">增量值(默认=1)</param>
        /// <returns></returns>
        public static async Task<decimal> ZIncrByAsync(string key, string member, decimal increment = 1)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZIncrByAsync(key, member, increment);
        }

        /// <summary>
        /// 通过索引区间返回有序集合成指定区间内的成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<string[]> ZRangeAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeAsync(key, start, stop);
        }

        /// <summary>
        /// 通过索引区间返回有序集合成指定区间内的成员
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<T[]> ZRangeAsync<T>(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeAsync<T>(key, start, stop);
        }

        /// <summary>
        /// 通过索引区间返回有序集合成指定区间内的成员和分数
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<(string member, decimal score)[]> ZRangeWithScoresAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeWithScoresAsync(key, start, stop);
        }

        /// <summary>
        /// 通过索引区间返回有序集合成指定区间内的成员和分数
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<(T member, decimal score)[]> ZRangeWithScoresAsync<T>(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeWithScoresAsync<T>(key, start, stop);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<string[]> ZRangeByScoreAsync(string key, decimal min, decimal max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreAsync(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<T[]> ZRangeByScoreAsync<T>(string key, decimal min, decimal max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreAsync<T>(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<string[]> ZRangeByScoreAsync(string key, string min, string max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreAsync(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<T[]> ZRangeByScoreAsync<T>(string key, string min, string max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreAsync<T>(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员和分数
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(string member, decimal score)[]> ZRangeByScoreWithScoresAsync(string key, decimal min, decimal max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreWithScoresAsync(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员和分数
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(T member, decimal score)[]> ZRangeByScoreWithScoresAsync<T>(string key, decimal min, decimal max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreWithScoresAsync<T>(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员和分数
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(string member, decimal score)[]> ZRangeByScoreWithScoresAsync(string key, string min, string max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreWithScoresAsync(key, min, max, limit, offset);
        }

        /// <summary>
        /// 通过分数返回有序集合指定区间内的成员和分数
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(T member, decimal score)[]> ZRangeByScoreWithScoresAsync<T>(string key, string min, string max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByScoreWithScoresAsync<T>(key, min, max, limit, offset);
        }

        /// <summary>
        /// 返回有序集合中指定成员的索引
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <returns></returns>
        public static async Task<long?> ZRankAsync(string key, object member)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRankAsync(key, member);
        }

        /// <summary>
        /// 移除有序集合中的一个或多个成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">一个或多个成员</param>
        /// <returns></returns>
        public static async Task<long> ZRemAsync<T>(string key, params T[] member)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRemAsync(key, member);
        }

        /// <summary>
        /// 移除有序集合中给定的排名区间的所有成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<long> ZRemRangeByRankAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRemRangeByRankAsync(key, start, stop);
        }

        /// <summary>
        /// 移除有序集合中给定的分数区间的所有成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <returns></returns>
        public static async Task<long> ZRemRangeByScoreAsync(string key, decimal min, decimal max)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRemRangeByScoreAsync(key, min, max);
        }

        /// <summary>
        /// 移除有序集合中给定的分数区间的所有成员
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <returns></returns>
        public static async Task<long> ZRemRangeByScoreAsync(string key, string min, string max)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRemRangeByScoreAsync(key, min, max);
        }

        /// <summary>
        /// 返回有序集中指定区间内的成员，通过索引，分数从高到底
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<string[]> ZRevRangeAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeAsync(key, start, stop);
        }

        /// <summary>
        /// 返回有序集中指定区间内的成员，通过索引，分数从高到底
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<T[]> ZRevRangeAsync<T>(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);

            return await redisClient.ZRevRangeAsync<T>(key, start, stop);
        }

        /// <summary>
        /// 返回有序集中指定区间内的成员和分数，通过索引，分数从高到底
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<(string member, decimal score)[]> ZRevRangeWithScoresAsync(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeWithScoresAsync(key, start, stop);
        }

        /// <summary>
        /// 返回有序集中指定区间内的成员和分数，通过索引，分数从高到底
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        public static async Task<(T member, decimal score)[]> ZRevRangeWithScoresAsync<T>(string key, long start, long stop)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeWithScoresAsync<T>(key, start, stop);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员，分数从高到低排序
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<string[]> ZRevRangeByScoreAsync(string key, decimal max, decimal min, long? limit = null, long? offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreAsync(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员，分数从高到低排序
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<T[]> ZRevRangeByScoreAsync<T>(string key, decimal max, decimal min, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreAsync<T>(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员，分数从高到低排序
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<string[]> ZRevRangeByScoreAsync(string key, string max, string min, long? limit = null, long? offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreAsync(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员，分数从高到低排序
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<T[]> ZRevRangeByScoreAsync<T>(string key, string max, string min, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreAsync<T>(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员和分数，分数从高到低排序
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(string member, decimal score)[]> ZRevRangeByScoreWithScoresAsync(string key, decimal max, decimal min, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreWithScoresAsync(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员和分数，分数从高到低排序
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 decimal.MaxValue 10</param>
        /// <param name="min">分数最小值 decimal.MinValue 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(T member, decimal score)[]> ZRevRangeByScoreWithScoresAsync<T>(string key, decimal max, decimal min, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreWithScoresAsync<T>(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员和分数，分数从高到低排序
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(string member, decimal score)[]> ZRevRangeByScoreWithScoresAsync(string key, string max, string min, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreWithScoresAsync(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集中指定分数区间内的成员和分数，分数从高到低排序
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="max">分数最大值 +inf (10 10</param>
        /// <param name="min">分数最小值 -inf (1 1</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<(T member, decimal score)[]> ZRevRangeByScoreWithScoresAsync<T>(string key, string max, string min, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRangeByScoreWithScoresAsync<T>(key, max, min, limit, offset);
        }

        /// <summary>
        /// 返回有序集合中指定成员的排名，有序集成员按分数值递减(从大到小)排序
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <returns></returns>
        public static async Task<long?> ZRevRankAsync(string key, object member)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRevRankAsync(key, member);
        }

        /// <summary>
        /// 返回有序集中，成员的分数值
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <returns></returns>
        public static async Task<decimal?> ZScoreAsync(string key, object member)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZScoreAsync(key, member);
        }

        /// <summary>
        /// 迭代有序集合中的元素
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="cursor">位置</param>
        /// <param name="pattern">模式</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static async Task<RedisScan<(string member, decimal score)>> ZScanAsync(string key, int cursor, string pattern = null, int? count = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZScanAsync(key, cursor, pattern, count);
        }

        /// <summary>
        /// 迭代有序集合中的元素
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="cursor">位置</param>
        /// <param name="pattern">模式</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static async Task<RedisScan<(T member, decimal score)>> ZScanAsync<T>(string key, int cursor, string pattern = null, int? count = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZScanAsync<T>(key, cursor, pattern, count);
        }

        /// <summary>
        /// 当有序集合的所有成员都具有相同的分值时，有序集合的元素会根据成员的字典序来进行排序，这个命令可以返回给定的有序集合键 key 中，值介于 min 和 max 之间的成员。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <param name="max">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<string[]> ZRangeByLexAsync(string key, string min, string max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByLexAsync(key, min, max, limit, offset);
        }

        /// <summary>
        /// 当有序集合的所有成员都具有相同的分值时，有序集合的元素会根据成员的字典序来进行排序，这个命令可以返回给定的有序集合键 key 中，值介于 min 和 max 之间的成员。
        /// </summary>
        /// <typeparam name="T">byte[] 或其他类型</typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <param name="max">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <param name="limit">返回多少成员</param>
        /// <param name="offset">返回条件偏移位置</param>
        /// <returns></returns>
        public static async Task<T[]> ZRangeByLexAsync<T>(string key, string min, string max, long? limit = null, long offset = 0)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRangeByLexAsync<T>(key, min, max, limit, offset);
        }

        /// <summary>
        /// 当有序集合的所有成员都具有相同的分值时，有序集合的元素会根据成员的字典序来进行排序，这个命令可以返回给定的有序集合键 key 中，值介于 min 和 max 之间的成员。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <param name="max">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <returns></returns>
        public static async Task<long> ZRemRangeByLexAsync(string key, string min, string max)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZRemRangeByLexAsync(key, min, max);
        }

        /// <summary>
        /// 当有序集合的所有成员都具有相同的分值时，有序集合的元素会根据成员的字典序来进行排序，这个命令可以返回给定的有序集合键 key 中，值介于 min 和 max 之间的成员。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="min">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <param name="max">'(' 表示包含在范围，'[' 表示不包含在范围，'+' 正无穷大，'-' 负无限。 ZRANGEBYLEX zset - + ，命令将返回有序集合中的所有元素</param>
        /// <returns></returns>
        public static async Task<long> ZLexCountAsync(string key, string min, string max)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.ZLexCountAsync(key, min, max);
        }

        #endregion

        #region Geo redis-server 3.2

        /// <summary>
        /// 将指定的地理空间位置（纬度、经度、成员）添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="member">成员</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> GeoAddAsync(string key, decimal longitude, decimal latitude, object member)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoAddAsync(key, longitude, latitude, member);
        }
        /// <summary>
        /// 将指定的地理空间位置（纬度、经度、成员）添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="values">批量添加的值</param>
        /// <returns>添加到sorted set元素的数目，但不包括已更新score的元素。</returns>
        public static async Task<long> GeoAddAsync(string key, params (decimal longitude, decimal latitude, object member)[] values)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoAddAsync(key, values);
        }
        /// <summary>
        /// 将指定的地理空间位置（纬度、经度、成员）添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="values">批量添加的值</param>
        /// <returns>添加到sorted set元素的数目，但不包括已更新score的元素。</returns>
        public static async Task<long> GeoAddAsync(string key, params GeoAddDto[] values)
        {
            var redisClient = GetRedisClient(key);
            List<(decimal longitude, decimal latitude, object member)> list = new List<(decimal longitude, decimal latitude, object member)>();
            foreach (var item in values)
            {
                list.Add((item.Longitude, item.Latitude, item.Member));
            }
            return await redisClient.GeoAddAsync(key, list.ToArray());
        }

        /// <summary>
        /// 返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在， 那么命令返回空值。GEODIST 命令在计算距离时会假设地球为完美的球形， 在极限情况下， 这一假设最大会造成 0.5% 的误差。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member1">成员1</param>
        /// <param name="member2">成员2</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <returns>计算出的距离会以双精度浮点数的形式被返回。 如果给定的位置元素不存在， 那么命令返回空值。</returns>
        public static async Task<decimal?> GeoDistAsync(string key, object member1, object member2, GeoUnit unit = GeoUnit.m)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoDistAsync(key, member1, member2, unit);
        }

        /// <summary>
        /// 返回一个或多个位置元素的 Geohash 表示。通常使用表示位置的元素使用不同的技术，使用Geohash位置52点整数编码。由于编码和解码过程中所使用的初始最小和最大坐标不同，编码的编码也不同于标准。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="members">多个查询的成员</param>
        /// <returns>一个数组， 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。</returns>
        public static async Task<string[]> GeoHashAsync(string key, object[] members)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoHashAsync(key, members);
        }

        /// <summary>
        /// 从key里返回所有给定位置元素的位置（经度和纬度）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="members">多个查询的成员</param>
        /// <returns>GEOPOS 命令返回一个数组， 数组中的每个项都由两个元素组成： 第一个元素为给定位置元素的经度， 而第二个元素则为给定位置元素的纬度。当给定的位置元素不存在时， 对应的数组项为空值。</returns>
        public static async Task<(decimal longitude, decimal latitude)?[]> GeoPosAsync(string key, object[] members)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoPosAsync(key, members);
        }

        /// <summary>
        /// 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<string[]> GeoRadiusAsync(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusAsync(key, longitude, latitude, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<T[]> GeoRadiusAsync<T>(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusAsync<T>(key, longitude, latitude, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(string member, decimal dist)[]> GeoRadiusWithDistAsync(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusWithDistAsync(key, longitude, latitude, radius, unit, count, sorting);
        }
        /// <summary>
        /// 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(T member, decimal dist)[]> GeoRadiusWithDistAsync<T>(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusWithDistAsync<T>(key, longitude, latitude, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离、经度、纬度）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(string member, decimal dist, decimal longitude, decimal latitude)[]> GeoRadiusWithDistAndCoordAsync(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusWithDistAndCoordAsync(key, longitude, latitude, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离、经度、纬度）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(T member, decimal dist, decimal longitude, decimal latitude)[]> GeoRadiusWithDistAndCoordAsync<T>(string key, decimal longitude, decimal latitude, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusWithDistAndCoordAsync<T>(key, longitude, latitude, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的成员为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<string[]> GeoRadiusByMemberAsync(string key, object member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusByMemberAsync(key, member, radius, unit, count, sorting);
        }
        /// <summary>
        /// 以给定的成员为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<T[]> GeoRadiusByMemberAsync<T>(string key, object member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusByMemberAsync<T>(key, member, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的成员为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(string member, decimal dist)[]> GeoRadiusByMemberWithDistAsync(string key, object member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusByMemberWithDistAsync(key, member, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的成员为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(T member, decimal dist)[]> GeoRadiusByMemberWithDistAsync<T>(string key, object member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusByMemberWithDistAsync<T>(key, member, radius, unit, count, sorting);
        }
        /// <summary>
        /// 以给定的成员为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离、经度、纬度）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(string member, decimal dist, decimal longitude, decimal latitude)[]> GeoRadiusByMemberWithDistAndCoordAsync(string key, object member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusByMemberWithDistAndCoordAsync(key, member, radius, unit, count, sorting);
        }

        /// <summary>
        /// 以给定的成员为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素（包含距离、经度、纬度）。
        /// </summary>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="member">成员</param>
        /// <param name="radius">距离</param>
        /// <param name="unit">m 表示单位为米；km 表示单位为千米；mi 表示单位为英里；ft 表示单位为英尺；</param>
        /// <param name="count">虽然用户可以使用 COUNT 选项去获取前 N 个匹配元素， 但是因为命令在内部可能会需要对所有被匹配的元素进行处理， 所以在对一个非常大的区域进行搜索时， 即使只使用 COUNT 选项去获取少量元素， 命令的执行速度也可能会非常慢。 但是从另一方面来说， 使用 COUNT 选项去减少需要返回的元素数量， 对于减少带宽来说仍然是非常有用的。</param>
        /// <param name="sorting">排序</param>
        /// <returns></returns>
        public static async Task<(T member, decimal dist, decimal longitude, decimal latitude)[]> GeoRadiusByMemberWithDistAndCoordAsync<T>(string key, object member, decimal radius, GeoUnit unit = GeoUnit.m, long? count = null, GeoOrderBy? sorting = null)
        {
            var redisClient = GetRedisClient(key);
            return await redisClient.GeoRadiusByMemberWithDistAndCoordAsync<T>(key, member, radius, unit, count, sorting);
        }

        #endregion


        #region 指定CSRedisClient

        #region Hash
        /// <summary>
        /// 同时将多个 field-value (域-值)对设置到哈希表 key 中
        /// </summary>
        /// <param name="redisClient">Redis客户端</param>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="fieldValues">一个或多个 field value 值</param>
        /// <returns></returns>
        public static async Task<bool> HMSetAsync(CSRedisClient redisClient, string key, params HashAddDto[] fieldValues)
        {
            List<object> list = new List<object>();
            foreach (var item in fieldValues)
            {
                list.Add(item.Field);
                list.Add(item.Value);
            }
            return await redisClient.HMSetAsync(key, list.ToArray());
        }
        #endregion

        #region Sorted Set

        /// <summary>
        /// 向有序集合添加一个或多个成员，或者更新已存在成员的分数
        /// </summary>
        /// <param name="redisClient">Redis客户端</param>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="scoreMembers">一个或多个成员分数</param>
        /// <returns></returns>
        public static async Task<long> ZAddAsync(CSRedisClient redisClient, string key, params SortedSetAddDto[] scoreMembers)
        {
            List<(decimal, object)> list = new List<(decimal, object)>();
            foreach (var item in scoreMembers)
            {
                list.Add((item.Score, item.Member));
            }
            return await redisClient.ZAddAsync(key, list.ToArray());
        }

        #endregion

        #region Geo redis
        /// <summary>
        /// 将指定的地理空间位置（纬度、经度、成员）添加到指定的key中。这些数据将会存储到sorted set这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。
        /// </summary>
        /// <param name="redisClient">Redis客户端</param>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="values">批量添加的值</param>
        /// <returns>添加到sorted set元素的数目，但不包括已更新score的元素。</returns>
        public static async Task<long> GeoAddAsync(CSRedisClient redisClient, string key, params GeoAddDto[] values)
        {
            List<(decimal longitude, decimal latitude, object member)> list = new List<(decimal longitude, decimal latitude, object member)>();
            foreach (var item in values)
            {
                list.Add((item.Longitude, item.Latitude, item.Member));
            }
            return await redisClient.GeoAddAsync(key, list.ToArray());
        }
        #endregion

        #region 查询keys
        /// <summary>
        /// 查询keys，会加上前缀
        /// </summary>
        /// <param name="redisClient">Redis客户端</param>
        /// <param name="pattern">匹配</param>
        /// <returns>key数组</returns>
        public static async Task<string[]> KeysAsync(CSRedisClient redisClient, string pattern)
        {
            string prefix = GetPrefix(redisClient);
            pattern = string.Concat(prefix, pattern);
            var keys = await redisClient.KeysAsync(pattern);
            return RemovePrefix(prefix, keys);
        }
        #endregion

        #endregion

        #region 使用分布式锁调用业务逻辑

        /// <summary>
        /// 使用分布式锁调用业务逻辑
        /// </summary>
        /// <param name="lockKey">锁的Key名称</param>
        /// <param name="func">Action业务</param>
        /// <param name="millisecondsTimeout">最多锁定毫秒数</param>
        /// <param name="millisecondsDelay">每次等待毫秒数</param>
        public static async Task LockAsync(string lockKey, Func<Task> func, int millisecondsTimeout = 10000, int millisecondsDelay = 500)
        {
            var redisClient = GetRedisClient(lockKey);
            await LockAsync(redisClient, lockKey, func, millisecondsTimeout, millisecondsDelay);
        }

        /// <summary>
        /// 使用分布式锁调用业务逻辑
        /// </summary>
        /// <param name="redisClient">redis客户端</param>
        /// <param name="lockKey">锁的Key名称</param>
        /// <param name="func">Action业务</param>
        /// <param name="millisecondsTimeout">最多锁定毫秒数</param>
        /// <param name="millisecondsDelay">每次等待毫秒数</param>
        public static async Task LockAsync(CSRedisClient redisClient, string lockKey, Func<Task> func, int millisecondsTimeout = 10000, int millisecondsDelay = 500)
        {
            int index = 0;
            while (true)
            {
                //加入分布式锁，防止并发出现异常
                if (await redisClient.SetNxAsync(lockKey, "1"))
                {
                    //设定锁的过期时间
                    await redisClient.ExpireAsync(lockKey, TimeSpan.FromMilliseconds(millisecondsTimeout));
                    try
                    {
                        await func();
                        break;
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                    finally
                    {
                        //删除锁key
                        await redisClient.DelAsync(lockKey);
                    }
                }
                else
                {
                    //如果不是第一次循环，且锁的过期时间为 -1，则表示异常，删除锁
                    if (index > 0 && (await redisClient.TtlAsync(lockKey)) == -1)
                    {
                        //删除锁key
                        await redisClient.DelAsync(lockKey);
                    }
                    else
                    {
                        Thread.Sleep(millisecondsDelay);
                    }
                    index++;
                }

            }
        }

        #endregion

        #region 委托方法调用

        #region String
        #region String

        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <param name="expireFunc">设置过期时间方法</param>
        /// <returns></returns>
        private static async Task<string> GetValueAsync(CSRedisClient redisClient, string key, Func<Task<string>> getValue, bool resetExpire, Func<Task<bool>> expireFunc)
        {
            if (await redisClient.ExistsAsync(key))
            {
                var value = await redisClient.GetAsync(key);
                if (resetExpire)
                {
                    await expireFunc();
                }
                return value;
            }
            else
            {
                var value = await getValue();
                await redisClient.SetAsync(key, value);
                await expireFunc();
                return value;
            }
        }

        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(CSRedisClient redisClient, string key, Func<Task<string>> getValue, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                TimeSpan? expire = GetExpire(key);
                if (expire.HasValue)
                {
                    return await redisClient.ExpireAsync(key, expire.Value);
                }
                return true;
            });
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="seconds">过期秒数</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(CSRedisClient redisClient, string key, Func<Task<string>> getValue, int seconds, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                return await redisClient.ExpireAsync(key, seconds);
            });
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(CSRedisClient redisClient, string key, Func<Task<string>> getValue, TimeSpan expire, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                return await redisClient.ExpireAsync(key, expire);
            });
        }

        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">指定的过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(CSRedisClient redisClient, string key, Func<Task<string>> getValue, DateTime expire, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                return await redisClient.ExpireAtAsync(key, expire);
            });
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(string key, Func<Task<string>> getValue, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, resetExpire);
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="seconds">过期秒数</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(string key, Func<Task<string>> getValue, int seconds, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, seconds, resetExpire);
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(string key, Func<Task<string>> getValue, TimeSpan expire, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, expire, resetExpire);
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">指定的过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<string> GetAsync(string key, Func<Task<string>> getValue, DateTime expire, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, expire, resetExpire);
        }

        #endregion

        #region 泛型

        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <param name="expireFunc">设置过期时间方法</param>
        /// <returns></returns>
        private static async Task<T> GetValueAsync<T>(CSRedisClient redisClient, string key, Func<Task<T>> getValue, bool resetExpire, Func<Task<bool>> expireFunc)
        {
            if (await redisClient.ExistsAsync(key))
            {
                var value = await redisClient.GetAsync<T>(key);
                if (resetExpire)
                {
                    await expireFunc();
                }
                return value;
            }
            else
            {
                var value = await getValue();
                await redisClient.SetAsync(key, value);
                await expireFunc();
                return value;
            }
        }

        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(CSRedisClient redisClient, string key, Func<Task<T>> getValue, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                TimeSpan? expire = GetExpire(key);
                if (expire.HasValue)
                {
                    return await redisClient.ExpireAsync(key, expire.Value);
                }
                return true;
            });

        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="seconds">过期秒数</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(CSRedisClient redisClient, string key, Func<Task<T>> getValue, int seconds, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                return await redisClient.ExpireAsync(key, seconds);
            });
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(CSRedisClient redisClient, string key, Func<Task<T>> getValue, TimeSpan expire, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                return await redisClient.ExpireAsync(key, expire);
            });
        }

        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisClient">客户端</param>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">指定的过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(CSRedisClient redisClient, string key, Func<Task<T>> getValue, DateTime expire, bool resetExpire = false)
        {
            return await GetValueAsync(redisClient, key, getValue, resetExpire, async () =>
            {
                return await redisClient.ExpireAtAsync(key, expire);
            });
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, Func<Task<T>> getValue, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, resetExpire);
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="seconds">过期秒数</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, Func<Task<T>> getValue, int seconds, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, seconds, resetExpire);
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, Func<Task<T>> getValue, TimeSpan expire, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, expire, resetExpire);
        }
        /// <summary>
        /// 获取指定Key的值
        /// 如何key不存在，则从委托中获取
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key</param>
        /// <param name="getValue">委托</param>
        /// <param name="expire">指定的过期时间</param>
        /// <param name="resetExpire">重置过期时间</param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, Func<Task<T>> getValue, DateTime expire, bool resetExpire = false)
        {
            var redisClient = GetRedisClient(key);
            return await GetAsync(redisClient, key, getValue, expire, resetExpire);
        }

        #endregion

        #endregion


        #endregion
    }
}
